#include "ogreapplication.h"
#include <OgreErrorDialog.h>
#include <OgreKeyEvent.h>
#define ZOOM 100

//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Interface of MyApplication
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
class MyApplication : public OgreApplication, Ogre::MouseListener
{
public:
    MyApplication();
    virtual void init();
    virtual bool frameStarted(const Ogre::FrameEvent& evt);
    virtual void keyPressed(Ogre::KeyEvent* e);
    virtual void keyClicked(Ogre::KeyEvent* e);
    virtual void keyReleased(Ogre::KeyEvent* e);
    void ligne(Ogre::Vector3 pos1, Ogre::Vector3 pos2);
    virtual void mousePressed(Ogre::MouseEvent*)
    {};
    virtual void mouseReleased(Ogre::MouseEvent*);

    virtual void mouseClicked(Ogre::MouseEvent*)
    {};
    virtual void mouseEntered(Ogre::MouseEvent*)
    {};
    virtual void mouseExited(Ogre::MouseEvent*)
    {};
private:
    Ogre::RaySceneQuery* mRaySceneQuery;
    Ogre::Entity*        mSelected;
    Ogre::Overlay*  mPanelOverlay;
    Ogre::String nomFic;
    Ogre::OverlayElement* fic;
    int nbLignes;
    Ogre::MaterialPtr ligneMaterial;

};

using namespace Ogre;
using namespace std;

//************************************************************
// Implementation of MyApplication
//************************************************************
MyApplication::MyApplication()
        : OgreApplication("VISAGEFS"), mSelected(NULL)
{}
void
MyApplication::mouseReleased(Ogre::MouseEvent* e)
{

    if (e->getButtonID() == InputEvent::BUTTON0_MASK) // Left
    {
        // Deselect old one if any
        if (mSelected) mSelected->getParentSceneNode()->showBoundingBox(false);
        fic->setCaption("");

// Use a ray scene query to find where we clicked
        Ray mouseRay = mCamera->getCameraToViewportRay(e->getX(),e->getY());
        mRaySceneQuery->setRay(mouseRay);
        mRaySceneQuery->setSortByDistance(true);
        RaySceneQueryResult &result = mRaySceneQuery->execute();
        if (!result.empty())
        {
            RaySceneQueryResultEntry& re = result.front();
            if (re.movable && re.movable->getMovableType() == "Entity")
            {
                mSelected = (Entity*)(re.movable);
                mSelected->getParentSceneNode()->showBoundingBox(true);
                fic->setCaption("Nom du fichier: " + mSelected->getName());
               // mCamera->setPosition(mSelected->getParentNode()->getWorldPosition() + Vector3(0,0,500));
                //mCamera->lookAt(mSelected->getParentNode()->getWorldPosition());
            }
        }
    }
}

void MyApplication::ligne(Vector3 pos1, Vector3 pos2)
{
    ManualObject* myManualObject =  mSceneManager->createManualObject("Ligne" + nbLignes);
    SceneNode* myManualObjectNode = mSceneManager->getRootSceneNode()->createChildSceneNode("LigneNode" + nbLignes);


    myManualObject->begin("ligneMaterial" , Ogre::RenderOperation::OT_LINE_LIST);
    myManualObject->position(pos1);
    myManualObject->position(pos2);
    myManualObject->end();

    myManualObjectNode->attachObject(myManualObject);
    nbLignes++;
}

void
MyApplication::init()
{
    nbLignes = 0;

    ligneMaterial = MaterialManager::getSingleton().create("ligneMaterial","debugger");
    ligneMaterial->setReceiveShadows(false);
    ligneMaterial->getTechnique(0)->setLightingEnabled(true);
    ligneMaterial->getTechnique(0)->getPass(0)->setDiffuse(0,0,1,0);
    ligneMaterial->getTechnique(0)->getPass(0)->setAmbient(0,0,1);
    ligneMaterial->getTechnique(0)->getPass(0)->setSelfIllumination(0,0,1);


    mSceneManager->setAmbientLight(ColourValue(0.7f,0.7f,1.0f));


    // Adds a cube
    Entity *cube1 = mSceneManager->createEntity("Rep1","cube.mesh");
    SceneNode* cube1Node = mSceneManager->getRootSceneNode()->createChildSceneNode("cube1Node");
    cube1Node->scale(0.5,0.5,0.5);
    cube1Node->attachObject(cube1);
    Real r = cube1->getBoundingRadius();

    Entity *cube2 = mSceneManager->createEntity("Rep2","cube.mesh");
    SceneNode* cube2Node = cube1Node->createChildSceneNode("cube2Node");
    cube2Node->translate(-r*5,r*5,0);
    cube2Node->attachObject(cube2);


    Entity *cube3 = mSceneManager->createEntity("Fichier1","cube.mesh");
    SceneNode* cube3Node = cube1Node->createChildSceneNode("cube3Node");
    cube3Node->translate(r*5,r*5,0);
    cube3Node->attachObject(cube3);


    Entity *cube4 = mSceneManager->createEntity("Fichier2","cube.mesh");
    SceneNode* cube4Node = cube3Node->createChildSceneNode("cube4Node");
    cube4Node->translate(r*5,r*5,0);
    cube4Node->attachObject(cube4);


    ligne(cube3Node->getWorldPosition(), cube3Node->getParent()->getWorldPosition());
    ligne(cube2Node->getWorldPosition(), cube2Node->getParent()->getWorldPosition());
    ligne(cube4Node->getWorldPosition(), cube4Node->getParent()->getWorldPosition());

    // Activate shadows
    mSceneManager->setShadowTechnique(Ogre::SHADOWTYPE_STENCIL_MODULATIVE);
    mSceneManager->setShadowColour(Ogre::ColourValue(0.5f,0.5f,0.5f));
    cube1->setCastShadows(true);
    cube2->setCastShadows(true);
    cube3->setCastShadows(true);
    cube4->setCastShadows(true);
    mDebugPanelOverlay = OverlayManager::getSingleton().getByName("PanelOverlay");
    mDebugPanelOverlay->show();

    mSceneManager->setSkyBox(true,"Examples/EveningSkyBox",50);
    mRaySceneQuery = mSceneManager->createRayQuery(Ray());

    fic = OverlayManager::getSingleton().getOverlayElement("Fichier");
    mEventProcessor->addMouseListener(this);

}
bool
MyApplication::frameStarted(const FrameEvent& evt)
{
    return OgreApplication::frameStarted(evt);
}


void MyApplication::keyPressed(KeyEvent *e)
{
    if (e->getKey() == KC_LEFT)
    {
        move = Vector3(-1.0,0.0,0.0);
        e->consume();
    }
    else if (e->getKey() == KC_RIGHT)
    {
        move = Vector3(1.0,0.0,0.0);
        e->consume();
    }
    else if (e->getKey() == KC_UP)
    {
        move = Vector3(0.0,1.0,0.0);
        e->consume();
    }
    else if (e->getKey() == KC_DOWN)
    {
        move = Vector3(0.0,-1.0,0.0);
        e->consume();
    }
    else if (e->getKey() == KC_I)
    {
        mCamera->setPosition(0,0,500);
        mCamera->lookAt(0,0,0);
       if (mSelected) mSelected->getParentSceneNode()->showBoundingBox(false);
        fic->setCaption("");
        e->consume();
    }
}


void MyApplication::keyClicked(KeyEvent *e)
{
    if (e->getKey() == KC_ESCAPE)
    {
        requestQuit();
        e->consume();
    }
    else if (e->getKey() == KC_SUBTRACT)
    {
        mCamera->moveRelative(Vector3(0,0,ZOOM));
        e->consume();
    }
    else if (e->getKey() == KC_ADD)
    {
        mCamera->moveRelative(Vector3(0,0,-ZOOM));
        e->consume();
    }

}


void MyApplication::keyReleased(KeyEvent *e)
{
    move = Vector3(0,0,0);
    e->consume();
}
int main(int, char **)
{
    MyApplication application;
    try
    {
        application.addResourceLocationFrom("resources.cfg");
        application.create("plugins.cfg","ogre.cfg","ogre.log",ST_GENERIC);
        application.run();
    }
    catch (Exception& e)
    {
        ErrorDialog* dlg = PlatformManager::getSingleton().createErrorDialog();
        dlg->display(e.getFullDescription());
        delete dlg;
        return 1;
    }
    return 0;
}


